package com.third.device.mg.serialport.help.netty

import com.third.device.mg.serialport.MGSerialPort
import com.third.device.mg.serialport.listener.BootstrapHelperNotifyListener
import com.third.device.mg.serialport.listener.MGNettyConnectListener
import com.third.device.mg.serialport.utils.SLog
import com.third.device.mg.serialport.utils.mainThread
import com.third.device.mg.serialport.utils.toHexString
import io.netty.bootstrap.Bootstrap
import io.netty.channel.ChannelFuture
import io.netty.channel.ChannelOption
import io.netty.channel.nio.NioEventLoopGroup
import io.netty.channel.socket.nio.NioSocketChannel


/**
 * company 广东玛格家居有限公司
 * @author smoker
 * @Date 2021/12/31
 * Description:客户端辅助启动类 助手
 */
internal class BootstrapHelper(
    val ip: String,
    val port: Int,
    loopGroup: NioEventLoopGroup,
    private val notifyListener: BootstrapHelperNotifyListener
) {

    private var boots = Bootstrap()
    private var future: ChannelFuture? = null
    private val clientInitializer by lazy { ClientChannelInitializer(ip, port) }

    companion object {
        private const val TAG = "${MGSerialPort.BASE_TAG}:BootstrapHelper: "
    }

    fun setListener(listener: MGNettyConnectListener) {
        clientInitializer.setListener(listener)
    }

    init {
        boots.group(loopGroup)
            .channel(NioSocketChannel::class.java)
            .remoteAddress(ip, port)
            .option(ChannelOption.TCP_NODELAY, true) //无阻塞
            .option(ChannelOption.SO_KEEPALIVE, true) //长连接
            //.option(ChannelOption.SO_TIMEOUT, 1000) //收发超时
            .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000)//连接超时时间
            .handler(clientInitializer)
        connect()
    }


    fun isConnect() = future?.channel()?.isActive ?: false


    fun connect() {
        future = boots.connect(ip, port)
        future?.addListener {
            it?.let { f ->
                f.mainThread {
                    notifyListener.operationComplete(f.isSuccess ,ip, port)
                    if (f.isSuccess) {
                        SLog.d(TAG, "Netty 连接成功 $ip:$port")
                        addChannelListener()//连接成后才去监听通道
                        clientInitializer.clientHandler.listener?.connectBack(ip, port)
                    } else {
                        SLog.d(TAG, "Netty 连接失败 $ip:$port")
                        clientInitializer.clientHandler.listener?.disconnectBack(ip, port)
                    }
                }
            }
        }
    }

    /**
     * 监听通道
     */
    private fun addChannelListener(){
        future?.channel()?.closeFuture()?.addListener {
            SLog.d(TAG, "Netty 通道关闭 $ip:$port ")
            it.mainThread {
                clientInitializer.clientHandler.listener?.disconnectBack(ip, port)
            }
        }
    }

    /**
     * 写入数据
     * @param data 写入的数据
     */
    fun writeData(data: ByteArray) {
        future?.let { mFuture ->
            mFuture.channel()?.let {
                val mPromise = it.newPromise()
                mPromise.addListener { result ->
                    result.mainThread {
                        val str = if (result.isSuccess) "Successful" else "Error"
                        SLog.d(TAG, "Write $str: $ip:$port ==> ${data.toHexString()}")
                        clientInitializer.clientHandler.listener?.writeBack(
                            ip,
                            port,
                            result.isSuccess,
                            data
                        )
                    }
                }
                it.writeAndFlush(data, mPromise)
            } ?: let {
                it.mainThread {
                    clientInitializer.clientHandler.listener?.errorBack(
                        ip, port,
                        Throwable("Channel is null")
                    )
                }
            }
        } ?: let {
            it.mainThread {
                clientInitializer.clientHandler.listener?.errorBack(
                    ip, port,
                    Throwable("ChannelFuture is null")
                )
            }
        }
    }

    /**
     * 关闭
     */
    fun disconnect() {
        future?.let {
            it.channel()?.disconnect()
            it.channel()?.close()
        }
    }
}